<!DOCTYPE html>



  


<html class="theme-next pisces use-motion" lang="en">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.2" rel="stylesheet" type="text/css">


  <meta name="keywords" content="Hexo, NexT">





  <link rel="alternate" href="/atom.xml" title="Hero's notebooks" type="application/atom+xml">




  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.2">






<meta name="description" content="hero&apos;s notebooks">
<meta property="og:type" content="website">
<meta property="og:title" content="Hero&#39;s notebooks">
<meta property="og:url" content="https://chenzk1.github.io/page/2/index.html">
<meta property="og:site_name" content="Hero&#39;s notebooks">
<meta property="og:description" content="hero&apos;s notebooks">
<meta property="og:locale" content="en">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Hero&#39;s notebooks">
<meta name="twitter:description" content="hero&apos;s notebooks">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://chenzk1.github.io/page/2/">





  <title>Hero's notebooks</title>
  














</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="en">

  
  
    
  

  <div class="container sidebar-position-left 
   page-home 
 ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Hero's notebooks</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">Sometimes naive.</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            Categories
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            Search
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="Searching..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/链表-反转链表/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/链表-反转链表/" itemprop="url">链表-反转链表</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h1 id="反转整个链表"><a href="#反转整个链表" class="headerlink" title="反转整个链表"></a>反转整个链表</h1><h2 id="递归"><a href="#递归" class="headerlink" title="递归"></a>递归</h2><ul>
<li>递归往上走的时候，每进一轮迭代，当前节点与之前节点的链接未变化，且head.next节点总是在已反转的链表末端，因此可以用head.next.next = head。</li>
<li>递归需要badcase</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">class Solution:</span><br><span class="line">    def reverseList(self, head: ListNode) -&gt; ListNode:</span><br><span class="line">        if head.next==None:</span><br><span class="line">            return head</span><br><span class="line">        last = reverseList(head.next)</span><br><span class="line">        head.next.next = head</span><br><span class="line">        head.next = null</span><br><span class="line">        return last</span><br></pre></td></tr></table></figure>
<h2 id="迭代"><a href="#迭代" class="headerlink" title="迭代"></a>迭代</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">class Solution:</span><br><span class="line">    def reverseList(self, head: ListNode) -&gt; ListNode:</span><br><span class="line">        curr = head</span><br><span class="line">        prev = None</span><br><span class="line">        while curr != None:</span><br><span class="line">            temp = curr.next</span><br><span class="line">            prev = curr</span><br><span class="line">            curr.next = prev</span><br><span class="line">            curr = temp</span><br><span class="line">        return prev</span><br></pre></td></tr></table></figure>
<h1 id="反转前n个链表"><a href="#反转前n个链表" class="headerlink" title="反转前n个链表"></a>反转前n个链表</h1><h2 id="递归-1"><a href="#递归-1" class="headerlink" title="递归"></a>递归</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">class Solution:</span><br><span class="line">    def reverseN(self, head: ListNode, n: int) -&gt; ListNode:</span><br><span class="line">        if n==1:</span><br><span class="line">            successor = head.next</span><br><span class="line">            return head</span><br><span class="line"></span><br><span class="line">        last = self.reverseN(head.next, n-1)</span><br><span class="line">        head.next.next = head</span><br><span class="line">        head.next = successor</span><br><span class="line">        </span><br><span class="line">        return last</span><br></pre></td></tr></table></figure>
<h1 id="反转一部分"><a href="#反转一部分" class="headerlink" title="反转一部分"></a>反转一部分</h1><h2 id="递归-使用前有函数"><a href="#递归-使用前有函数" class="headerlink" title="递归 使用前有函数"></a>递归 使用前有函数</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">class Solution:</span><br><span class="line">    def reverseBetween(self, head: ListNode, m: int, n: int) -&gt; ListNode:</span><br><span class="line">        if m==1:</span><br><span class="line">            return self.reverseN(head, n)</span><br><span class="line">        head.next = self.reverseBetween(head.next, m-1, n-1)</span><br><span class="line">        return head</span><br></pre></td></tr></table></figure>
<h2 id="迭代-1"><a href="#迭代-1" class="headerlink" title="迭代"></a>迭代</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">class Solution:</span><br><span class="line">    def reverseBetween(self, head: ListNode, m: int, n: int) -&gt; ListNode:</span><br><span class="line">        dummy = ListNode(-1)</span><br><span class="line">        dummy.next = head</span><br><span class="line">        prev = dummy</span><br><span class="line">        for _ in range(m-1):</span><br><span class="line">            prev = prev.next</span><br><span class="line">        curr = prev.next</span><br><span class="line">        node = None</span><br><span class="line">        for _ in range(n-m+1):</span><br><span class="line">            temp = curr.next</span><br><span class="line">            curr.next = node</span><br><span class="line">            node = curr</span><br><span class="line">            curr = temp</span><br><span class="line"></span><br><span class="line">        prev.next.next = curr</span><br><span class="line">        prev.next = node</span><br><span class="line">        return dummy.next</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">class Solution:</span><br><span class="line">    def reverseBetween(self, head: ListNode, m: int, n: int) -&gt; ListNode:</span><br><span class="line">        dummy = ListNode(-1)</span><br><span class="line">        dummy.next = head</span><br><span class="line">        prev = dummy</span><br><span class="line">        for _ in range(m-1):</span><br><span class="line">            prev = prev.next</span><br><span class="line">        start = prev.next</span><br><span class="line">        tail = start.next</span><br><span class="line">        for _ in range(n-m):</span><br><span class="line">            start.next = tail.next</span><br><span class="line">            tail.next = start</span><br><span class="line">            prev.next = tail</span><br><span class="line">            tail = start.next</span><br><span class="line">        return dummy.next</span><br></pre></td></tr></table></figure>
          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/卡方分布及卡方检验/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/卡方分布及卡方检验/" itemprop="url">卡方分布及卡方检验</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p><a href="https://blog.csdn.net/cuitzjd/article/details/80755310" target="_blank" rel="noopener">Doc1</a><br><a href="https://cosx.org/2010/11/hypotheses-testing/" target="_blank" rel="noopener">Doc2</a></p>
<h3 id="统计检验"><a href="#统计检验" class="headerlink" title="统计检验"></a>统计检验</h3><ul>
<li>出发点：小概率事件发生则假设不成立。可以检验一个样本与总体的差异，也可以检验一个样本集与另一个样本集的差异。</li>
<li>e.g. 观察到某个班级男女生身高的均值有差距，要证明这一点，先假设其”没有差距“，然后做相关的检验，如果检验出来有差距这个事件的概率小于某个值，则说明假设不成立。即一个具有足够小概率的事件发生了，这不是偶然。</li>
<li>第一类错误：原假设为真，检验的结果劝你放弃原假设。其概率为α。显著性水平。</li>
<li>第二类错误：原假设为假，检验的结果劝你接受原假设。概率为1-α。</li>
<li>显著性检验，即只限定第一类错误。当经过检验发现p&gt;α，则说明检验、总体这两样本之间不存在显著性差异，因此接受原假设；否则，说明一个很小概率的事件发生了，不接受原假设。</li>
<li>不同的检验方式有不同的前提。</li>
</ul>
<h3 id="T"><a href="#T" class="headerlink" title="T"></a>T</h3><ul>
<li><p><strong>用于样本量较小，总体标准差σ未知的正态分布。</strong></p>
</li>
<li><p>单总体检验：一个样本的平均数与已知的总体平均数的差异是否显著。</p>
</li>
<li><p>双总体样本检验：一个样本与另一个样本的差异。</p>
</li>
</ul>
<h3 id="F"><a href="#F" class="headerlink" title="F"></a>F</h3><ul>
<li>两个样本的总体方差是否相等。</li>
</ul>
<h3 id="卡方"><a href="#卡方" class="headerlink" title="卡方"></a>卡方</h3><h4 id="卡方检验"><a href="#卡方检验" class="headerlink" title="卡方检验"></a>卡方检验</h4><p><img src="https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&amp;quality=100&amp;size=b4000_4000&amp;sec=1512961717&amp;di=6133a04e10dc72b22bfb76fca025156d&amp;src=http://pic.baike.soso.com/p/20130619/20130619123748-1653885327.jpg" alt></p>
<ul>
<li><p>原假设为两者分布无差异、不相关等。</p>
</li>
<li><p>卡方值越大，实际（假设）与理论（根据原假设求得的概率值/统计量）差异越大，即假设的错误程度越大，超过阈值，则推翻假设。</p>
<p>若求得的卡方值落在阈值之上，说明小概率事件(e.g. 5%)发生了，则推翻原假设，说明两者差异的程度确实够大，即两者有差异；否则有95%的置信程度说明两者无差异。</p>
</li>
<li><p>参数有：自由度、置信水平。</p>
<p>例如，看喝牛奶与感冒有没有关系。给定置信度β，确定卡方值阈值x。</p>
<p>原假设：无关。</p>
<p>卡方值：先在原假设的基础上求出理论分布，然后看理论分布与实际分布的差异性（卡方值）。</p>
<p>查表，看有没有超过阈值，若超过，说明小概率（显著性水平：1-β）事件发生，推翻原假设，两者有关。</p>
</li>
</ul>
<h4 id="卡方分布"><a href="#卡方分布" class="headerlink" title="卡方分布"></a>卡方分布</h4><p>n个相互独立且均服从标准正态分布的随机变量，其平方和服从卡方分布。</p>
<p><img src="https://img-blog.csdn.net/20180109180130184?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc25vd2Ryb3B0dWxpcA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt></p>
<h4 id="卡方分箱"><a href="#卡方分箱" class="headerlink" title="卡方分箱"></a>卡方分箱</h4><ul>
<li><p>算法步骤：</p>
<ul>
<li><p>初始化：排序，每个实例属于一个一个区间</p>
</li>
<li><p>合并区间：</p>
<ul>
<li><p>计算每一对相邻区间的卡方值</p>
</li>
<li><p>将卡方值最小的一对区间合并</p>
<p>$$  \mathrm{X}^{2}=\sum_{i=1}^{2} \sum_{j=1}^{2} \frac{\left(A_{i j}-E_{i j}\right)^{2}}{E_{i j}}  $$</p>
<p>其中，Ai,j为第i区间第j类的实例的数量，Ei,j为期望频率（整体分布，整体分布计算的时候还是用的这俩区间的数值）=Ni*(Cj/N)，Cj为j类在整体分布中的比例，Ni为i区间样本数</p>
<p>例如label有0和1，有两个区间，即[[3,4], [5,7]]</p>
<p>A11=3,A12=4… E11=7*8/19</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>原理：假设这俩区间没差异，其卡方值代表了该假设（由实际分布得出的统计量）与理论（整体样本[特征]分布）的差异程度，越小则说明俩越接近，假设越成立。</p>
<p>评分卡模型中，第i区间第j类的实例：类是指区间中有多少类特征，实例指其对应的label</p>
</li>
<li><p>阈值：显著性水平+自由度（比类别数量少1）确定。</p>
</li>
</ul>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/两种logloss/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/两种logloss/" itemprop="url">LR-logloss</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <ol>
<li>LR中，若0，1分类：<br>$$<br>\begin{array}{l}{\mathbb{P}(y=1 | z)=\sigma(z)=\frac{1}{1+e^{-z}}} \ {\mathbb{P}(y=0 | z)=1-\sigma(z)=\frac{1}{1+e^{z}}}\end{array}<br>$$<br>即：<br>$$<br>\mathbb{P}(y | z)=\sigma(z)^{y}(1-\sigma(z))^{1-y}<br>$$<br>极大似然：<br>$$<br>L(z)=\log \left(\prod_{i}^{m} \mathbb{P}\left(y_{i} | z_{i}\right)\right)=-\sum_{i}^{m} \log \left(\mathbb{P}\left(y_{i} | z_{i}\right)\right)=\sum_{i}^{m}-y_{i} z_{i}+\log \left(1+e^{z_{i}}\right)<br>$$<br>损失函数：<br>$$<br>l(z)=-\log \left(\prod_{i}^{m} \mathbb{P}\left(y_{i} | z_{i}\right)\right)=-\sum_{i}^{m} \log \left(\mathbb{P}\left(y_{i} | z_{i}\right)\right)=\sum_{i}^{m}-y_{i} z_{i}+\log \left(1+e^{z_{i}}\right)<br>$$</li>
</ol>
<ol start="2">
<li><p>1，-1分类：<br>$$<br>\begin{aligned} \mathbb{P}(y | z) &amp;=\sigma(y z) \ &amp;=\frac{1}{1+e^{-y z}} \end{aligned}<br>$$<br>分开表示跟0，1分类是一样的</p>
<p>损失函数：<br>$$<br>L(z)=-\log \left(\prod_{j}^{m} \mathbb{P}\left(y_{j} | z_{j}\right)\right)=-\sum_{j}^{m} \log \left(\mathbb{P}\left(y_{j} | z_{j}\right)\right)=\sum_{j}^{m} \log \left(1+e^{-y_{j} z_{j}}\right)<br>$$</p>
</li>
</ol>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/卷积神经网络(手写字的识别)/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/卷积神经网络(手写字的识别)/" itemprop="url">CNN-手写字的识别</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">数据集：MNIST手写数字集</span><br><span class="line">训练集：<span class="number">42</span>,<span class="number">000</span>个<span class="number">0</span><span class="number">-9</span>手写数字的图像</span><br><span class="line">测试集：有<span class="number">28</span>,<span class="number">000</span>个无label样本</span><br><span class="line">每个图像的大小是<span class="number">28</span>×<span class="number">28</span>=<span class="number">784</span>个像素</span><br><span class="line">目标：使用卷积神经网络识别图像是什么数字</span><br></pre></td></tr></table></figure>
<h3 id="导入相关包"><a href="#导入相关包" class="headerlink" title="导入相关包"></a>导入相关包</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Python的内置垃圾收集。用来删除一些变量，并收集必要的空间来保存RAM。</span></span><br><span class="line"><span class="keyword">import</span> gc </span><br><span class="line"><span class="comment"># 用来生成随机数。</span></span><br><span class="line"><span class="keyword">import</span> random <span class="keyword">as</span> rd </span><br><span class="line"><span class="comment">#用来检查运行时间。</span></span><br><span class="line"><span class="keyword">import</span> time </span><br><span class="line"><span class="comment"># 在数据增强部分，我们使用圆周率旋转图像。</span></span><br><span class="line"><span class="keyword">from</span> math <span class="keyword">import</span> pi </span><br><span class="line"><span class="comment"># 用Keras来构建我们的CNN模型。它使用TensorFlow作为后端。</span></span><br><span class="line"><span class="keyword">import</span> keras </span><br><span class="line"><span class="comment"># 绘制手写的数字图像。</span></span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt </span><br><span class="line"><span class="comment"># 矩阵操作。</span></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np </span><br><span class="line"><span class="comment"># 操作数据，比如加载和输出</span></span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="comment"># 用TensorFlow作为数据增强部分</span></span><br><span class="line"><span class="keyword">import</span> tensorflow <span class="keyword">as</span> tf</span><br><span class="line"><span class="comment"># 用来建立学习速率衰减的模型</span></span><br><span class="line"><span class="keyword">from</span> keras.callbacks <span class="keyword">import</span> ReduceLROnPlateau, EarlyStopping</span><br><span class="line"><span class="comment"># 构建CNN所需要的一些基本构件。 </span></span><br><span class="line"><span class="keyword">from</span> keras.layers <span class="keyword">import</span> (BatchNormalization, Conv2D, Dense, Dropout, Flatten,</span><br><span class="line">                          MaxPool2D, ReLU)</span><br><span class="line"><span class="comment"># 图像显示。</span></span><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"><span class="comment"># 将数据分解为训练和验证两部分。</span></span><br><span class="line"><span class="keyword">from</span> sklearn.model_selection <span class="keyword">import</span> train_test_split</span><br><span class="line">%matplotlib inline</span><br></pre></td></tr></table></figure>
<pre><code>Using TensorFlow backend.
</code></pre><h3 id="数据处理"><a href="#数据处理" class="headerlink" title="数据处理"></a>数据处理</h3><p><strong>导入数据</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">print(<span class="string">"Loading..."</span>)</span><br><span class="line">path = <span class="string">"E:/机器学习/Tensorflow学习/data/"</span></span><br><span class="line">data_train = pd.read_csv(path + <span class="string">"train.csv"</span>,engine=<span class="string">"python"</span>)</span><br><span class="line">data_test = pd.read_csv(path + <span class="string">"test.csv"</span>,engine=<span class="string">"python"</span>)</span><br><span class="line">print(<span class="string">"Done!"</span>)</span><br></pre></td></tr></table></figure>
<pre><code>Loading...
Done!
</code></pre><p><strong>查看数据集的大小</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">print(<span class="string">"Training data: &#123;&#125; rows, &#123;&#125; columns."</span>.format(data_train.shape[<span class="number">0</span>], data_train.shape[<span class="number">1</span>]))</span><br><span class="line">print(<span class="string">"Test data: &#123;&#125; rows, &#123;&#125; columns."</span>.format(data_test.shape[<span class="number">0</span>], data_test.shape[<span class="number">1</span>]))</span><br></pre></td></tr></table></figure>
<pre><code>Training data: 42000 rows, 785 columns.
Test data: 28000 rows, 784 columns.
</code></pre><p>训练集有42000行，785列，其中包括784个像素和一个标签，标注了这张图片是什么数字。</p>
<p>测试数据有28000行，没有标签。</p>
<p><strong>数据集拆分成x（图像数据）和y（标签）</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">x_train = data_train.values[:, <span class="number">1</span>:]</span><br><span class="line">y_train = data_train.values[:, <span class="number">0</span>]</span><br></pre></td></tr></table></figure>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">convert_2d</span><span class="params">(x)</span>:</span></span><br><span class="line">    <span class="string">"""x: 2d numpy array. m*n data image.</span></span><br><span class="line"><span class="string">       return a 3d image data. m * height * width * channel."""</span></span><br><span class="line">    <span class="keyword">if</span> len(x.shape) == <span class="number">1</span>:</span><br><span class="line">        m = <span class="number">1</span></span><br><span class="line">        height = width = int(np.sqrt(x.shape[<span class="number">0</span>]))</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        m = x.shape[<span class="number">0</span>]</span><br><span class="line">        height = width = int(np.sqrt(x.shape[<span class="number">1</span>]))</span><br><span class="line"></span><br><span class="line">    x_2d = np.reshape(x, (m, height, width, <span class="number">1</span>))</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> x_2d</span><br></pre></td></tr></table></figure>
<p><strong>查看图像</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">x_display = convert_2d(data_train.values[<span class="number">0</span>, <span class="number">1</span>:])</span><br><span class="line">plt.imshow(x_display.squeeze())</span><br></pre></td></tr></table></figure>
<pre><code>&lt;matplotlib.image.AxesImage at 0x22b013e7780&gt;
</code></pre><p><img src="output_14_1.png" alt="png"></p>
<h3 id="数据增强"><a href="#数据增强" class="headerlink" title="数据增强"></a>数据增强</h3><p>在这里，我们直接研究数据增强。<br>当您没有足够的数据或想要扩展数据以提高性能时，数据增强是一种非常有用的技术。<br>在这场比赛中，数据增强基本上是指在不损害图像可识别性的前提下，对图像进行切割、旋转和缩放。<br>这里我使用了缩放、平移、白噪声和旋转。<br>随着数据的增加，您可以预期1-2%的准确性提高。</p>
<p><strong>放大</strong></p>
<p>使用crop_image函数来裁剪围绕中心的图像的一部分，调整其大小并将其保存为增强数据。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">crop_image</span><span class="params">(x, y, min_scale)</span>:</span></span><br><span class="line">    <span class="string">"""x: 2d(m*n) numpy array. 1-dimension image data;</span></span><br><span class="line"><span class="string">       y: 1d numpy array. The ground truth label;</span></span><br><span class="line"><span class="string">       min_scale: float. The minimum scale for cropping.</span></span><br><span class="line"><span class="string">       return zoomed images.</span></span><br><span class="line"><span class="string">    # 该函数对图像进行裁剪，放大裁剪后的部分，并将其作为增强数据"""</span></span><br><span class="line">    <span class="comment"># 将数据转换为二维图像。图像应该是一个m*h*w*c数字数组。</span></span><br><span class="line">    images = convert_2d(x)</span><br><span class="line">    <span class="comment"># m是图像的个数。由于这是从0到255的灰度图像，所以它只有一个通道。</span></span><br><span class="line">    m, height, width, channel = images.shape</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 原始图像的tf张量</span></span><br><span class="line">    img_tensor = tf.placeholder(tf.int32, [<span class="number">1</span>, height, width, channel])</span><br><span class="line">    <span class="comment"># tf tensor for 4 coordinates for corners of the cropped image</span></span><br><span class="line">    box_tensor = tf.placeholder(tf.float32, [<span class="number">1</span>, <span class="number">4</span>])</span><br><span class="line">    box_idx = [<span class="number">0</span>]</span><br><span class="line">    crop_size = np.array([height, width])</span><br><span class="line">    <span class="comment"># 裁剪并调整图像张量</span></span><br><span class="line">    cropped_img_tensor = tf.image.crop_and_resize(img_tensor, box_tensor, box_idx, crop_size)</span><br><span class="line">    <span class="comment"># numpy array for the cropped image</span></span><br><span class="line">    cropped_img = np.zeros((m, height, width, <span class="number">1</span>))</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.Session() <span class="keyword">as</span> sess:</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> range(m):</span><br><span class="line">            </span><br><span class="line">            <span class="comment"># randomly select a scale between [min_scale, min(min_scale + 0.05, 1)]</span></span><br><span class="line">            rand_scale = np.random.randint(min_scale * <span class="number">100</span>, np.minimum(min_scale * <span class="number">100</span> + <span class="number">5</span>, <span class="number">100</span>)) / <span class="number">100</span></span><br><span class="line">            <span class="comment"># calculate the 4 coordinates</span></span><br><span class="line">            x1 = y1 = <span class="number">0.5</span> - <span class="number">0.5</span> * rand_scale</span><br><span class="line">            x2 = y2 = <span class="number">0.5</span> + <span class="number">0.5</span> * rand_scale</span><br><span class="line">            <span class="comment"># lay down the cropping area</span></span><br><span class="line">            box = np.reshape(np.array([y1, x1, y2, x2]), (<span class="number">1</span>, <span class="number">4</span>))</span><br><span class="line">            <span class="comment"># save the cropped image</span></span><br><span class="line">            cropped_img[i:i + <span class="number">1</span>, :, :, :] = sess.run(cropped_img_tensor, feed_dict=&#123;img_tensor: images[i:i + <span class="number">1</span>], box_tensor: box&#125;)</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># flat the 2d image</span></span><br><span class="line">    cropped_img = np.reshape(cropped_img, (m, <span class="number">-1</span>))</span><br><span class="line">    cropped_img = np.concatenate((y.reshape((<span class="number">-1</span>, <span class="number">1</span>)), cropped_img), axis=<span class="number">1</span>).astype(int)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> cropped_img</span><br></pre></td></tr></table></figure>
<p><strong>平移</strong> </p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">translate</span><span class="params">(x, y, dist)</span>:</span></span><br><span class="line">    <span class="string">"""x: 2d(m*n) numpy array. 1-dimension image data;</span></span><br><span class="line"><span class="string">       y: 1d numpy array. The ground truth label;</span></span><br><span class="line"><span class="string">       dist: float. Percentage of height/width to shift.</span></span><br><span class="line"><span class="string">       return translated images.</span></span><br><span class="line"><span class="string">       这个函数将图像移动到4个不同的方向。</span></span><br><span class="line"><span class="string">       裁剪图像的一部分，移动，用0填充左边的部分"""</span></span><br><span class="line">    <span class="comment"># 将一维图像数据转换为m*h*w*c数组</span></span><br><span class="line">    images = convert_2d(x)</span><br><span class="line">    m, height, width, channel = images.shape</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># set 4 groups of anchors. The first 4 int in a certain group lay down the area we crop.</span></span><br><span class="line">    <span class="comment"># The last 4 sets the area to be moved to. E.g.,</span></span><br><span class="line">    <span class="comment"># new_img[new_top:new_bottom, new_left:new_right] = img[top:bottom, left:right]</span></span><br><span class="line">    anchors = []</span><br><span class="line">    anchors.append((<span class="number">0</span>, height, int(dist * width), width, <span class="number">0</span>, height, <span class="number">0</span>, width - int(dist * width)))</span><br><span class="line">    anchors.append((<span class="number">0</span>, height, <span class="number">0</span>, width - int(dist * width), <span class="number">0</span>, height, int(dist * width), width))</span><br><span class="line">    anchors.append((int(dist * height), height, <span class="number">0</span>, width, <span class="number">0</span>, height - int(dist * height), <span class="number">0</span>, width))</span><br><span class="line">    anchors.append((<span class="number">0</span>, height - int(dist * height), <span class="number">0</span>, width, int(dist * height), height, <span class="number">0</span>, width))</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># new_images: d*m*h*w*c array. The first dimension is the 4 directions.</span></span><br><span class="line">    new_images = np.zeros((<span class="number">4</span>, m, height, width, channel))</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">4</span>):</span><br><span class="line">        <span class="comment"># shift the image</span></span><br><span class="line">        top, bottom, left, right, new_top, new_bottom, new_left, new_right = anchors[i]</span><br><span class="line">        new_images[i, :, new_top:new_bottom, new_left:new_right, :] = images[:, top:bottom, left:right, :]</span><br><span class="line">    </span><br><span class="line">    new_images = np.reshape(new_images, (<span class="number">4</span> * m, <span class="number">-1</span>))</span><br><span class="line">    y = np.tile(y, (<span class="number">4</span>, <span class="number">1</span>)).reshape((<span class="number">-1</span>, <span class="number">1</span>))</span><br><span class="line">    new_images = np.concatenate((y, new_images), axis=<span class="number">1</span>).astype(int)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> new_images</span><br></pre></td></tr></table></figure>
<p><strong>添加白噪声</strong></p>
<p>现在我们给图像添加一些白噪声。我们随机选取一些像素，用均匀分布的噪声代替它们。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_noise</span><span class="params">(x, y, noise_lvl)</span>:</span></span><br><span class="line">    <span class="string">"""x: 2d(m*n) numpy array. 1-dimension image data;</span></span><br><span class="line"><span class="string">       y: 1d numpy array. The ground truth label;</span></span><br><span class="line"><span class="string">       noise_lvl: float. Percentage of pixels to add noise in.</span></span><br><span class="line"><span class="string">       return images with white noise.</span></span><br><span class="line"><span class="string">       This function randomly picks some pixels and replace them with noise."""</span></span><br><span class="line">    m, n = x.shape</span><br><span class="line">    <span class="comment"># calculate the # of pixels to add noise in</span></span><br><span class="line">    noise_num = int(noise_lvl * n)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> range(m):</span><br><span class="line">        <span class="comment"># generate n random numbers, sort it and choose the first noise_num indices</span></span><br><span class="line">        <span class="comment"># which equals to generate random numbers w/o replacement</span></span><br><span class="line">        noise_idx = np.random.randint(<span class="number">0</span>, n, n).argsort()[:noise_num]</span><br><span class="line">        <span class="comment"># replace the chosen pixels with noise from 0 to 255</span></span><br><span class="line">        x[i, noise_idx] = np.random.randint(<span class="number">0</span>, <span class="number">255</span>, noise_num)</span><br><span class="line"></span><br><span class="line">    noisy_data = np.concatenate((y.reshape((<span class="number">-1</span>, <span class="number">1</span>)), x), axis=<span class="number">1</span>).astype(<span class="string">"int"</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> noisy_data</span><br></pre></td></tr></table></figure>
<p><strong>旋转</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">rotate_image</span><span class="params">(x, y, max_angle)</span>:</span></span><br><span class="line">    <span class="string">"""x: 2d(m*n) numpy array. 1-dimension image data;</span></span><br><span class="line"><span class="string">       y: 1d numpy array. The ground truth label;</span></span><br><span class="line"><span class="string">       max_angle: int. The maximum degree for rotation.</span></span><br><span class="line"><span class="string">       return rotated images.</span></span><br><span class="line"><span class="string">       This function rotates the image for some random degrees(0.5 to 1 * max_angle degree)."""</span></span><br><span class="line">    images = convert_2d(x)</span><br><span class="line">    m, height, width, channel = images.shape</span><br><span class="line">    </span><br><span class="line">    img_tensor = tf.placeholder(tf.float32, [m, height, width, channel])</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># half of the images are rotated clockwise. The other half counter-clockwise</span></span><br><span class="line">    <span class="comment"># positive angle: [max/2, max]</span></span><br><span class="line">    <span class="comment"># negative angle: [360-max/2, 360-max]</span></span><br><span class="line">    rand_angle_pos = np.random.randint(max_angle / <span class="number">2</span>, max_angle, int(m / <span class="number">2</span>))</span><br><span class="line">    rand_angle_neg = np.random.randint(-max_angle, -max_angle / <span class="number">2</span>, m - int(m / <span class="number">2</span>)) + <span class="number">360</span></span><br><span class="line">    rand_angle = np.transpose(np.hstack((rand_angle_pos, rand_angle_neg)))</span><br><span class="line">    np.random.shuffle(rand_angle)</span><br><span class="line">    <span class="comment"># convert the degree to radian</span></span><br><span class="line">    rand_angle = rand_angle / <span class="number">180</span> * pi</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># rotate the images</span></span><br><span class="line">    rotated_img_tensor = tf.contrib.image.rotate(img_tensor, rand_angle)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.Session() <span class="keyword">as</span> sess:</span><br><span class="line">        rotated_imgs = sess.run(rotated_img_tensor, feed_dict=&#123;img_tensor: images&#125;)</span><br><span class="line">    </span><br><span class="line">    rotated_imgs = np.reshape(rotated_imgs, (m, <span class="number">-1</span>))</span><br><span class="line">    rotated_imgs = np.concatenate((y.reshape((<span class="number">-1</span>, <span class="number">1</span>)), rotated_imgs), axis=<span class="number">1</span>)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> rotated_imgs</span><br></pre></td></tr></table></figure>
<p><strong>合并</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">start = time.clock()</span><br><span class="line">print(<span class="string">"Augment the data..."</span>)</span><br><span class="line">cropped_imgs = crop_image(x_train, y_train, <span class="number">0.9</span>)</span><br><span class="line">translated_imgs = translate(x_train, y_train, <span class="number">0.1</span>)</span><br><span class="line">noisy_imgs = add_noise(x_train, y_train, <span class="number">0.1</span>)</span><br><span class="line">rotated_imgs = rotate_image(x_train, y_train, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">data_train = np.vstack((data_train, cropped_imgs, translated_imgs, noisy_imgs, rotated_imgs))</span><br><span class="line">np.random.shuffle(data_train)</span><br><span class="line">print(<span class="string">"Done!"</span>)</span><br><span class="line">time_used = int(time.clock() - start)</span><br><span class="line">print(<span class="string">"Time used: &#123;&#125;s."</span>.format(time_used))</span><br></pre></td></tr></table></figure>
<pre><code>G:\Anaconda\lib\site-packages\ipykernel_launcher.py:1: DeprecationWarning: time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead
  &quot;&quot;&quot;Entry point for launching an IPython kernel.


Augment the data...

WARNING: The TensorFlow contrib module will not be included in TensorFlow 2.0.
For more information, please see:
  * https://github.com/tensorflow/community/blob/master/rfcs/20180907-contrib-sunset.md
  * https://github.com/tensorflow/addons
If you depend on functionality not listed there, please file an issue.

Done!
Time used: 26s.


G:\Anaconda\lib\site-packages\ipykernel_launcher.py:11: DeprecationWarning: time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead
  # This is added back by InteractiveShellApp.init_path()
</code></pre><h3 id="数据准备"><a href="#数据准备" class="headerlink" title="数据准备"></a>数据准备</h3><p><strong>检查数据</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">x_train = data_train[:, <span class="number">1</span>:]</span><br><span class="line">y_train = data_train[:, <span class="number">0</span>]</span><br><span class="line">x_test = data_test.values</span><br><span class="line">print(<span class="string">"Augmented training data: &#123;&#125; rows, &#123;&#125; columns."</span>.format(data_train.shape[<span class="number">0</span>], data_train.shape[<span class="number">1</span>]))</span><br></pre></td></tr></table></figure>
<pre><code>Augmented training data: 336000 rows, 785 columns.
</code></pre><p>使用数据增强之后的训练数据总共有33万6千行，是原来的8倍。</p>
<p><strong>向量转化为一个矩阵</strong></p>
<p>因为CNN接受的是输入是二维的图像，我们需要将向量转化为一个矩阵<br>格式：$m(图像数量)×h(图像高度)×w(图像宽度)×c(图像通道数量)$</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">x_train = convert_2d(x_train)</span><br><span class="line">x_test = convert_2d(x_test)</span><br></pre></td></tr></table></figure>
<p><strong>将类别型数据转换成哑变量</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">num_classes = <span class="number">10</span></span><br><span class="line">y_train = keras.utils.to_categorical(y_train, num_classes)</span><br></pre></td></tr></table></figure>
<p>为了加快CNN优化速度，缩小像素值的范围。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">x_train = x_train / <span class="number">255</span></span><br><span class="line">x_test = x_test / <span class="number">255</span></span><br></pre></td></tr></table></figure>
<p><strong>划分训练集，验证集</strong></p>
<p>为了验证模型的好坏，用sklearn提供的一个函数来将数据按照9:1进行分割，90%为训练集，10%为验证集</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># generate a random seed for train-test-split</span></span><br><span class="line">seed = np.random.randint(<span class="number">1</span>, <span class="number">100</span>)</span><br><span class="line">x_train, x_dev, y_train, y_dev = train_test_split(x_train, y_train, test_size=<span class="number">0.1</span>, random_state=seed)</span><br></pre></td></tr></table></figure>
<p><strong>清理内存</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">del</span> data_train</span><br><span class="line"><span class="keyword">del</span> data_test</span><br><span class="line">gc.collect()</span><br></pre></td></tr></table></figure>
<pre><code>69
</code></pre><h3 id="搭建CNN模型"><a href="#搭建CNN模型" class="headerlink" title="搭建CNN模型"></a>搭建CNN模型</h3><p>一个普通的CNN通常包括三种类型的层，卷积层，池化层和全连接层。<br>我还在模型中添加了标准化层和dropout层。</p>
<ul>
<li><p>这里使用了5×5的卷积核，而不是3×3的。5×5的卷积核感受野更大，效果更好。</p>
</li>
<li><p>这里的批量归一化放在了ReLU激活函数之后，当然也可以放在激活函数之前。</p>
</li>
<li><p>Dropout使用了0.2的drop概率，意味着在Dropout层的输入中20%的像素点会被重置为0。</p>
</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 每个卷积层的信道数。 </span></span><br><span class="line">filters = (<span class="number">32</span>, <span class="number">32</span>, <span class="number">64</span>, <span class="number">64</span>)</span><br><span class="line"><span class="comment"># 每个conv层使用一个5x5内核</span></span><br><span class="line">kernel = (<span class="number">5</span>, <span class="number">5</span>)</span><br><span class="line"><span class="comment"># 在Dropout层的输入中20%的像素点会被重置为0。</span></span><br><span class="line">drop_prob = <span class="number">0.2</span></span><br><span class="line"></span><br><span class="line">model = keras.models.Sequential()</span><br><span class="line"></span><br><span class="line">model.add(Conv2D(filters[<span class="number">0</span>], kernel, padding=<span class="string">"same"</span>, input_shape=(<span class="number">28</span>, <span class="number">28</span>, <span class="number">1</span>),</span><br><span class="line">                 kernel_initializer=keras.initializers.he_normal()))</span><br><span class="line">model.add(BatchNormalization())</span><br><span class="line">model.add(ReLU())</span><br><span class="line">model.add(Conv2D(filters[<span class="number">0</span>], kernel, padding=<span class="string">"same"</span>,</span><br><span class="line">                 kernel_initializer=keras.initializers.he_normal()))</span><br><span class="line">model.add(BatchNormalization())</span><br><span class="line">model.add(ReLU())</span><br><span class="line">model.add(MaxPool2D())</span><br><span class="line">model.add(Dropout(drop_prob))</span><br><span class="line"></span><br><span class="line">model.add(Conv2D(filters[<span class="number">1</span>], kernel, padding=<span class="string">"same"</span>,</span><br><span class="line">                 kernel_initializer=keras.initializers.he_normal()))</span><br><span class="line">model.add(BatchNormalization())</span><br><span class="line">model.add(ReLU())</span><br><span class="line">model.add(MaxPool2D())</span><br><span class="line">model.add(Dropout(drop_prob))</span><br><span class="line"></span><br><span class="line">model.add(Conv2D(filters[<span class="number">2</span>], kernel, padding=<span class="string">"same"</span>,</span><br><span class="line">                 kernel_initializer=keras.initializers.he_normal()))</span><br><span class="line">model.add(BatchNormalization())</span><br><span class="line">model.add(ReLU())</span><br><span class="line">model.add(MaxPool2D())</span><br><span class="line">model.add(Dropout(drop_prob))</span><br><span class="line"></span><br><span class="line">model.add(Conv2D(filters[<span class="number">3</span>], kernel, padding=<span class="string">"same"</span>,</span><br><span class="line">                 kernel_initializer=keras.initializers.he_normal()))</span><br><span class="line">model.add(BatchNormalization())</span><br><span class="line">model.add(ReLU())</span><br><span class="line">model.add(MaxPool2D())</span><br><span class="line">model.add(Dropout(drop_prob))</span><br><span class="line"></span><br><span class="line"><span class="comment"># several fully-connected layers after the conv layers</span></span><br><span class="line">model.add(Flatten())</span><br><span class="line">model.add(Dropout(drop_prob))</span><br><span class="line">model.add(Dense(<span class="number">128</span>, activation=<span class="string">"relu"</span>))</span><br><span class="line">model.add(Dropout(drop_prob))</span><br><span class="line">model.add(Dense(num_classes, activation=<span class="string">"softmax"</span>))</span><br><span class="line"><span class="comment"># use the Adam optimizer to accelerate convergence</span></span><br><span class="line">model.compile(keras.optimizers.Adam(), <span class="string">"categorical_crossentropy"</span>, metrics=[<span class="string">"accuracy"</span>])</span><br></pre></td></tr></table></figure>
<pre><code>WARNING:tensorflow:From G:\Anaconda\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
WARNING:tensorflow:From G:\Anaconda\lib\site-packages\keras\backend\tensorflow_backend.py:3445: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.
Instructions for updating:
Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.
</code></pre><p><strong>查看模型架构</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">model.summary()</span><br></pre></td></tr></table></figure>
<pre><code>_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 28, 28, 32)        832       
_________________________________________________________________
batch_normalization_1 (Batch (None, 28, 28, 32)        128       
_________________________________________________________________
re_lu_1 (ReLU)               (None, 28, 28, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 28, 28, 32)        25632     
_________________________________________________________________
batch_normalization_2 (Batch (None, 28, 28, 32)        128       
_________________________________________________________________
re_lu_2 (ReLU)               (None, 28, 28, 32)        0         
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 14, 14, 32)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 14, 14, 32)        25632     
_________________________________________________________________
batch_normalization_3 (Batch (None, 14, 14, 32)        128       
_________________________________________________________________
re_lu_3 (ReLU)               (None, 14, 14, 32)        0         
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 7, 7, 32)          0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 7, 7, 32)          0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 7, 7, 64)          51264     
_________________________________________________________________
batch_normalization_4 (Batch (None, 7, 7, 64)          256       
_________________________________________________________________
re_lu_4 (ReLU)               (None, 7, 7, 64)          0         
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 3, 3, 64)          0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 3, 3, 64)          0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 3, 3, 64)          102464    
_________________________________________________________________
batch_normalization_5 (Batch (None, 3, 3, 64)          256       
_________________________________________________________________
re_lu_5 (ReLU)               (None, 3, 3, 64)          0         
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 1, 1, 64)          0         
_________________________________________________________________
dropout_4 (Dropout)          (None, 1, 1, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 64)                0         
_________________________________________________________________
dropout_5 (Dropout)          (None, 64)                0         
_________________________________________________________________
dense_1 (Dense)              (None, 128)               8320      
_________________________________________________________________
dropout_6 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                1290      
=================================================================
Total params: 216,330
Trainable params: 215,882
Non-trainable params: 448
_________________________________________________________________
</code></pre><p>The list above is the structure of my CNN model. It goes:</p>
<ul>
<li>(Conv-ReLU-BatchNormalization-MaxPooling-Dropout) x 4;</li>
<li><p>3 fully-connected(dense) layers with 1 dropout layer. Dense(64)-Dense(128)-Dropout-Dense(with softmax activation).</p>
</li>
<li><p>In CNN people often use 3x3 or 5x5 kernel. I found that with a 5x5 kernel, the model’s accuracy improved about 0.125%, which is quite a lot when you pass 99% threshold.</p>
</li>
<li>Convolutional layers and max pooling layers can extract some high-level traits from the pixels. With the <a href="https://en.wikipedia.org/wiki/Rectifier_(neural_networks" target="_blank" rel="noopener">ReLU</a>) unit the and max pooling, we also add non-linearity into the network;</li>
<li>Batch normalization helps the network converge faster since it keeps the input of every layer at the same scale;</li>
<li><a href="https://en.wikipedia.org/wiki/Convolutional_neural_network#Dropout" target="_blank" rel="noopener">Dropout</a> layers help us prevent overfitting by randomly drop some of the input units. With dropout our model won’t overfit to some specific extreme data or some noisy pixels;</li>
<li>The <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#Adam" target="_blank" rel="noopener">Adam optimizer</a> also accelerates the optimization. Usually when the dataset is too large, we use mini-batch gradient descent or stochastic gradient descent to save some training time. The randomness in MBGD or SGD means that the steps towards the optimum are zig-zag rather than straight forward. Adam, or Adaptive Moment Estimation, uses exponential moving average on the gradients and the secend moment of gradients to make the steps straight and in turn accelerate the optimization.</li>
</ul>
<h3 id="训练CNN"><a href="#训练CNN" class="headerlink" title="训练CNN"></a>训练CNN</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># number of epochs we run</span></span><br><span class="line">iters = <span class="number">100</span></span><br><span class="line"><span class="comment"># batch size. Number of images we train before we take one step in MBGD.</span></span><br><span class="line">batch_size = <span class="number">1024</span></span><br></pre></td></tr></table></figure>
<p>当我们接近最佳状态时，我们需要降低学习速度以防止过度学习。高学习率会使我们远离最佳状态。因此，当验证数据的准确性不再提高时，我将这个学习率衰减设置为降低它。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># monitor: :要监视的数量。当它不再显著改善时，我们就降低了学习速度</span></span><br><span class="line"><span class="comment"># factor: 新学习率=旧学习率 * factor</span></span><br><span class="line"><span class="comment"># patience:在降低学习速度之前，我们要等待的时间</span></span><br><span class="line"><span class="comment"># verbose: 是否显示信息</span></span><br><span class="line"><span class="comment"># min_lr: 最小的学习率</span></span><br><span class="line"></span><br><span class="line">lr_decay = ReduceLROnPlateau(monitor=<span class="string">"val_acc"</span>, factor=<span class="number">0.5</span>, patience=<span class="number">3</span>, verbose=<span class="number">1</span>, min_lr=<span class="number">1e-5</span>)</span><br><span class="line"><span class="comment"># 如果模型在验证数据上没有得到任何改善，可以设置早期停止，以防止过度拟合，并节省一些时间。当监控量没有提高时，提前停止训练。</span></span><br><span class="line">early_stopping = EarlyStopping(monitor=<span class="string">"val_acc"</span>, patience=<span class="number">7</span>, verbose=<span class="number">1</span>)</span><br></pre></td></tr></table></figure>
<p><strong>训练模型</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">print(<span class="string">"Training model..."</span>)</span><br><span class="line">fit_params = &#123;</span><br><span class="line">    <span class="string">"batch_size"</span>: batch_size,</span><br><span class="line">    <span class="string">"epochs"</span>: iters,</span><br><span class="line">    <span class="string">"verbose"</span>: <span class="number">1</span>,</span><br><span class="line">    <span class="string">"callbacks"</span>: [lr_decay, early_stopping],</span><br><span class="line">    <span class="string">"validation_data"</span>: (x_dev, y_dev)     <span class="comment"># data for monitoring the model accuracy</span></span><br><span class="line">&#125;</span><br><span class="line">model.fit(x_train, y_train, **fit_params)</span><br><span class="line">print(<span class="string">"Done!"</span>)</span><br></pre></td></tr></table></figure>
<pre><code>Training model...
WARNING:tensorflow:From G:\Anaconda\lib\site-packages\tensorflow\python\ops\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.cast instead.
Train on 302400 samples, validate on 33600 samples
Epoch 1/100
  3072/302400 [..............................] - ETA: 32:43 - loss: 2.6548 - acc: 0.1156
</code></pre><h3 id="模型评估"><a href="#模型评估" class="headerlink" title="模型评估"></a>模型评估</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">model.evaluate(x_dev, y_dev)</span><br></pre></td></tr></table></figure>
<pre><code>33600/33600 [==============================] - 3s 75us/step





[0.0018058670724439621, 0.9994047619047619]
</code></pre><p>evaluate这个方法会输出两个值，第一个是当期的损失函数值，第二个是模型的准确率。我们可以看到，模型的准确率在验证集上达到了99.84%！</p>
<h3 id="输出预测"><a href="#输出预测" class="headerlink" title="输出预测"></a>输出预测</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">y_pred = model.predict(x_test, batch_size=batch_size)</span><br><span class="line">y_pred = np.argmax(y_pred, axis=<span class="number">1</span>).reshape((<span class="number">-1</span>, <span class="number">1</span>))</span><br><span class="line">idx = np.reshape(np.arange(<span class="number">1</span>, len(y_pred) + <span class="number">1</span>), (len(y_pred), <span class="number">-1</span>))</span><br><span class="line">y_pred = np.hstack((idx, y_pred))</span><br><span class="line">y_pred = pd.DataFrame(y_pred, columns=[<span class="string">'ImageId'</span>, <span class="string">'Label'</span>])</span><br><span class="line">y_pred.to_csv(<span class="string">'y_pred.csv'</span>, index=<span class="literal">False</span>)</span><br></pre></td></tr></table></figure>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/基向量与坐标变换/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/基向量与坐标变换/" itemprop="url">基向量与坐标变换</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <ol>
<li><p>基与维数</p>
<ul>
<li>F：一个数集</li>
<li>V：F上的非空子集，相当于一个向量空间。{α1，α2…αm}是V中的一个有序向量组。</li>
</ul>
<p>基：{α1，α2…αm}线性无关且V中的向量都可以用{α1，α2…αm}，{α1，α2…αm}为V的一组基。V = L(α1，α2…αm)</p>
<p>维数：基中向量的个数。</p>
</li>
<li><p>坐标：向量关于基的坐标<br>$$<br>\alpha=x_{1} \alpha 1+x_{2} \alpha 2+\cdots, x_{m} \alpha m=\left(\alpha_{1}, \alpha_{2}, \cdots, \alpha_{m}\right)\left(\begin{array}{c}{x_{1}} \ {x_{2}} \ {\vdots} \ {x_{m}}\end{array}\right)<br>$$<br>(X1…xm)是向量α在基下的坐标</p>
</li>
<li><p>基变换与坐标变换</p>
<ul>
<li><p>基变换</p>
<p>(β1… βm) = A(α1… αm) </p>
<p>A为基α到基β的过渡矩阵</p>
</li>
<li><p>坐标变换</p>
<p>同一向量关于一个基的坐标x到关于另一个基的坐标y的变换</p>
</li>
</ul>
</li>
</ol>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/HMM（隐马尔可夫）/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/HMM（隐马尔可夫）/" itemprop="url">隐马尔科夫</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="最大熵模型"><a href="#最大熵模型" class="headerlink" title="最大熵模型"></a>最大熵模型</h2><ul>
<li><p>出发点：保留所有不确定性，将风险降到最小。</p>
</li>
<li><p>条件熵：$ H(Y|X) = -\sum\limits_{i=1}^{n}p(x_i,y_i)logp(y_i|x_i) = \sum\limits_{j=1}^{n}p(x_j)H(Y|x_j) $</p>
</li>
<li><p>最大熵模型：假设分类模型为一个条件概率分布P(Y|X)，X为特征，Y为输出，给定(X,Y)，用最大熵模型选择一个最好的分类模型。</p>
<p><a href="https://www.cnblogs.com/pinard/p/6093948.html" target="_blank" rel="noopener">Doc</a></p>
</li>
</ul>
<h2 id="隐马尔可夫"><a href="#隐马尔可夫" class="headerlink" title="隐马尔可夫"></a>隐马尔可夫</h2><ul>
<li>要解决的问题：1）基于序列；2）问题中有两类数据，一类是可以观测到的（观测序列），另一类是不能观测的（状态序列）。</li>
</ul>
<h3 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h3><ul>
<li><p>假设Q={q1,q2…qN}是<strong>所有可能</strong>的隐藏状态的集合，V={v1,v2…vM}是<strong>所有可能</strong>的观测状态的集合。</p>
</li>
<li><p>对于一个长度为T的序列，I={i1,i2…iT}为状态序列，O={o1,o2…oT}为观察序列。其中i∈q, o∈v</p>
</li>
<li><p>假设：</p>
<ul>
<li><p>齐次马尔科夫链假设。即任意时刻的隐藏状态只依赖于它前一个隐藏状态。如果在时刻tt的隐藏状态是it=qi,在时刻t+1t+1的隐藏状态是it+1=qj, 则从时刻t到时刻t+1的HMM状态转移概率aij可以表示为：</p>
<p>$ a_{ij} = P(i_{t+1} = q_j | i_t= q_i) $</p>
<p>aij的状态转移矩阵A=「aij」NxN</p>
</li>
<li><p>观察独立性假设。任意时刻的观察状态只依赖于当前时刻的隐藏状态。如果在时刻t的隐藏状态是it=qj, 而对应的观察状态为ot=vk, 则该时刻观察状态vk在隐藏状态qj下生成的概率为bj(k),满足：</p>
<p>$ b_j(k) = P(o_t = v_k | i_t= q_j) $</p>
<p>这样bj(k)可以组成观测状态生成的概率矩阵B:</p>
<p>$ B = \Big [b_j(k) \Big ]_{N \times M} $</p>
</li>
<li><p>此外，需要t=1时的隐藏状态概率分布II：</p>
<p>$ B = \Big [b_j(k) \Big ]_{N \times M} $</p>
</li>
</ul>
</li>
<li><p>一个HMM模型，可以由隐藏状态初始概率分布II，A、B状态转移矩阵和状态概率矩阵决定：</p>
<p>λ=(A,B,II)</p>
</li>
</ul>
<h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><ol>
<li>评估观察序列概率。即给定模型λ=(A,B,II)和观测序列O={o1,o2,…oT}，计算在模型λ下观测序列O出现的概率P(O|λ)。这个问题的求解需要用到前向后向算法。</li>
<li>模型参数学习问题。即给定观测序列O={o1,o2,…oT}，估计模型λ=(A,B,II)的参数，使该模型下观测序列的条件概率P(O|λ)最大。这个问题的求解需要用到基于EM算法的鲍姆-韦尔奇算法， 我们在这个系列的第三篇会详细讲解。这个问题是HMM模型三个问题中最复杂的。</li>
<li>预测问题，也称为解码问题。即给定模型λ=(A,B,II)和观测序列O={o1,o2,…oT}，求给定观测序列条件下，最可能出现的对应的状态序列，这个问题的求解需要用到基于动态规划的维特比算法，我们在这个系列的第四篇会详细讲解。这个问题是HMM模型三个问题中复杂度居中的算法。</li>
</ol>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/K-S、GINI/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/K-S、GINI/" itemprop="url">KS-GINI</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>##<strong>都是用来衡量模型区分度的</strong></p>
<h4 id="K-S"><a href="#K-S" class="headerlink" title="K-S"></a>K-S</h4><ul>
<li><p>KS(Kolmogorov-Smirnov)：KS用于模型风险区分能力进行评估，<br>指标衡量的是好坏样本累计分部之间的差值。<br>好坏样本累计差异越大，KS指标越大，那么模型的风险区分能力越强。</p>
</li>
<li><p>KS的计算步骤如下： </p>
<ol>
<li><p>计算每个评分区间的好坏账户数。 </p>
</li>
<li><p>计算每个评分区间的累计好账户数占总好账户数比率(good%)和累计坏账户数占总坏账户数比率(bad%)。 </p>
</li>
<li><p>计算每个评分区间累计坏账户占比与累计好账户占比差的绝对值（累计good%-累计bad%），然后对这些绝对值取最大值即得此评分卡的K-S值。</p>
</li>
</ol>
</li>
</ul>
<pre><code><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ks</span><span class="params">(df, y_true, y_pre, num=<span class="number">10</span>, good=<span class="number">0</span>, bad=<span class="number">1</span>)</span>:</span></span><br><span class="line">  <span class="string">'''</span></span><br><span class="line"><span class="string">  df为包含真实label和预测的概率值的DataFrame</span></span><br><span class="line"><span class="string">  y_true</span></span><br><span class="line"><span class="string">  '''</span></span><br><span class="line">    <span class="comment"># 1.将数据从小到大平均分成num组</span></span><br><span class="line">    df_ks = df.sort_values(y_pre).reset_index(drop=<span class="literal">True</span>)</span><br><span class="line">    df_ks[<span class="string">'rank'</span>] = np.floor((df_ks.index / len(df_ks) * num) + <span class="number">1</span>)</span><br><span class="line">    df_ks[<span class="string">'set_1'</span>] = <span class="number">1</span></span><br><span class="line">    <span class="comment"># 2.统计结果</span></span><br><span class="line">    result_ks = pd.DataFrame()</span><br><span class="line">    result_ks[<span class="string">'group_sum'</span>] = df_ks.groupby(<span class="string">'rank'</span>)[<span class="string">'set_1'</span>].sum()</span><br><span class="line">    result_ks[<span class="string">'group_min'</span>] = df_ks.groupby(<span class="string">'rank'</span>)[y_pre].min()</span><br><span class="line">    result_ks[<span class="string">'group_max'</span>] = df_ks.groupby(<span class="string">'rank'</span>)[y_pre].max()</span><br><span class="line">    result_ks[<span class="string">'group_mean'</span>] = df_ks.groupby(<span class="string">'rank'</span>)[y_pre].mean()</span><br><span class="line">    <span class="comment"># 3.最后一行添加total汇总数据</span></span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'group_sum'</span>] = df_ks[<span class="string">'set_1'</span>].sum()</span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'group_min'</span>] = df_ks[y_pre].min()</span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'group_max'</span>] = df_ks[y_pre].max()</span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'group_mean'</span>] = df_ks[y_pre].mean()</span><br><span class="line">    <span class="comment"># 4.好用户统计</span></span><br><span class="line">    result_ks[<span class="string">'good_sum'</span>] = df_ks[df_ks[y_true] == good].groupby(<span class="string">'rank'</span>)[<span class="string">'set_1'</span>].sum()</span><br><span class="line">    result_ks.good_sum.replace(np.nan, <span class="number">0</span>, inplace=<span class="literal">True</span>)</span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'good_sum'</span>] = result_ks[<span class="string">'good_sum'</span>].sum()</span><br><span class="line">    result_ks[<span class="string">'good_percent'</span>] = result_ks[<span class="string">'good_sum'</span>] / result_ks.loc[<span class="string">'total'</span>, <span class="string">'good_sum'</span>]</span><br><span class="line">    result_ks[<span class="string">'good_percent_cum'</span>] = result_ks[<span class="string">'good_sum'</span>].cumsum() / result_ks.loc[<span class="string">'total'</span>, <span class="string">'good_sum'</span>]</span><br><span class="line">    <span class="comment"># 5.坏用户统计</span></span><br><span class="line">    result_ks[<span class="string">'bad_sum'</span>] = df_ks[df_ks[y_true] == bad].groupby(<span class="string">'rank'</span>)[<span class="string">'set_1'</span>].sum()</span><br><span class="line">    result_ks.bad_sum.replace(np.nan, <span class="number">0</span>, inplace=<span class="literal">True</span>)</span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'bad_sum'</span>] = result_ks[<span class="string">'bad_sum'</span>].sum()</span><br><span class="line">    result_ks[<span class="string">'bad_percent'</span>] = result_ks[<span class="string">'bad_sum'</span>] / result_ks.loc[<span class="string">'total'</span>, <span class="string">'bad_sum'</span>]</span><br><span class="line">    result_ks[<span class="string">'bad_percent_cum'</span>] = result_ks[<span class="string">'bad_sum'</span>].cumsum() / result_ks.loc[<span class="string">'total'</span>, <span class="string">'bad_sum'</span>]</span><br><span class="line">    <span class="comment"># 6.计算ks值</span></span><br><span class="line">    result_ks[<span class="string">'diff'</span>] = result_ks[<span class="string">'bad_percent_cum'</span>] - result_ks[<span class="string">'good_percent_cum'</span>]</span><br><span class="line">    <span class="comment"># 7.更新最后一行total的数据</span></span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'bad_percent_cum'</span>] = np.nan</span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'good_percent_cum'</span>] = np.nan</span><br><span class="line">    result_ks.loc[<span class="string">'total'</span>, <span class="string">'diff'</span>] = result_ks[<span class="string">'diff'</span>].max()</span><br><span class="line">result_ks = result_ks.reset_index()</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> result_ks</span><br></pre></td></tr></table></figure>
</code></pre><h4 id="GINI"><a href="#GINI" class="headerlink" title="GINI"></a>GINI</h4><ul>
<li>GINI统计值衡量坏账户数在好账户数上的的累积分布与随机分布曲线之间的面积，好账户与坏账户分布之间的差异越大，GINI指标越高，表明模型的风险区分能力越强。</li>
<li>GINI系数的计算步骤如下： <ol>
<li>计算每个评分区间的好坏账户数。 </li>
<li>计算每个评分区间的累计好账户数占总好账户数比率（累计good%）和累计坏账户数占总坏账户数比率(累计bad%)。 </li>
<li>按照累计好账户占比和累计坏账户占比得出下图所示曲线ADC。 </li>
<li>计算出图中阴影部分面积，阴影面积占直角三角形ABC面积的百分比，即为GINI系数。</li>
</ol>
</li>
</ul>
<p><img src="https://img-blog.csdn.net/20171012171836445?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzQyMTYyOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="img"></p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/DS-绪论/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/DS-绪论/" itemprop="url">DS绪论</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Learning/" itemprop="url" rel="index">
                    <span itemprop="name">Learning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <ul>
<li><p>时间复杂度：<br>bigO bigΩ bigθ</p>
<p>分别为上、下、中</p>
</li>
</ul>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/7月24日/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/7月24日/" itemprop="url">Untitled</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="与滴滴金融的会议"><a href="#与滴滴金融的会议" class="headerlink" title="与滴滴金融的会议"></a>与滴滴金融的会议</h2><h3 id="乘客行为分在分析身份特征／平台贡献度／行为健康度／平台忠诚度这几个维度时，有没有涉及到POI特征数据？讨论POI数据缺失的可能替换方案。"><a href="#乘客行为分在分析身份特征／平台贡献度／行为健康度／平台忠诚度这几个维度时，有没有涉及到POI特征数据？讨论POI数据缺失的可能替换方案。" class="headerlink" title="乘客行为分在分析身份特征／平台贡献度／行为健康度／平台忠诚度这几个维度时，有没有涉及到POI特征数据？讨论POI数据缺失的可能替换方案。"></a>乘客行为分在分析身份特征／平台贡献度／行为健康度／平台忠诚度这几个维度时，有没有涉及到POI特征数据？讨论POI数据缺失的可能替换方案。</h3><p>当前有几类方案。</p>
<h3 id="金融视角，产品形态是车辆抵押贷款，需要聚焦在平台内有车乘客和橘子司机，我们需要重点围绕稳定性、收入、反欺诈、行为类四大类进行分析，具体情况开会介绍。"><a href="#金融视角，产品形态是车辆抵押贷款，需要聚焦在平台内有车乘客和橘子司机，我们需要重点围绕稳定性、收入、反欺诈、行为类四大类进行分析，具体情况开会介绍。" class="headerlink" title="金融视角，产品形态是车辆抵押贷款，需要聚焦在平台内有车乘客和橘子司机，我们需要重点围绕稳定性、收入、反欺诈、行为类四大类进行分析，具体情况开会介绍。"></a>金融视角，产品形态是车辆抵押贷款，需要聚焦在平台内有车乘客和橘子司机，我们需要重点围绕稳定性、收入、反欺诈、行为类四大类进行分析，具体情况开会介绍。</h3><ul>
<li><p>通过出行平台数据判断乘客稳定性时，乘客行为分需要加入哪些特征。</p>
<p>稳定性：</p>
</li>
</ul>
<p><img src="https://pic1.zhimg.com/80/v2-fea6a1111cb1274ca3368fad8d2e7a88_hd.jpg" alt="img"></p>
<ul>
<li>收入（消费水平）：平台价值维度。</li>
</ul>
<p><img src="https://pic4.zhimg.com/80/v2-88541a4212c7678e589df5badace3a07_hd.jpg" alt="img"></p>
<ul>
<li><p>反欺诈&amp;行为：</p>
<p>| 维度     | 子维度             | 因子                                         | 行为好坏                            | 备注 |<br>| ——– | —————— | ——————————————– | ———————————– | —- |<br>| 履约能力 | 历史借贷及履约表现 | 1.最近7天逾期支付率                          | 好：连续n单按时支付（3，5，10，20） |      |<br>|          |                    | 2.最近30天逾期支付率                         | 坏：7天内支付率                     |      |<br>|          |                    | 3.30天以上逾期支付率                         |                                     |      |<br>|          | 行为规范           | 1.平台作弊行为及表现（刷单，历史封禁）；     |                                     |      |<br>|          | 身份属性           | 1.实名认证？2.是否有司机账号                 |                                     |      |<br>|          | 发单习惯           | 平台发单行为（活跃度，发单习惯，收入稳定性） |                                     |      |<br>|          |                    |                                              |                                     |      |<br>|          |                    |                                              |                                     |      |<br>|          |                    |                                              |                                     |      |</p>
</li>
</ul>
<h3 id="乘客行为分在滴滴金融车抵贷产品形态下，数据风控层面的应用，从特征提取，数据建模，到输出决策。"><a href="#乘客行为分在滴滴金融车抵贷产品形态下，数据风控层面的应用，从特征提取，数据建模，到输出决策。" class="headerlink" title="乘客行为分在滴滴金融车抵贷产品形态下，数据风控层面的应用，从特征提取，数据建模，到输出决策。"></a>乘客行为分在滴滴金融车抵贷产品形态下，数据风控层面的应用，从特征提取，数据建模，到输出决策。</h3><h3 id="会议记录"><a href="#会议记录" class="headerlink" title="会议记录"></a>会议记录</h3><h4 id="进度"><a href="#进度" class="headerlink" title="进度"></a>进度</h4><h5 id="金融"><a href="#金融" class="headerlink" title="金融"></a>金融</h5><pre><code>- 以大数据风控作为下半年发展方向。
- 识别乘客的信用风险、需求，数据不是金融的，判断一个人是否有还贷意向。一部分是乘客，一部分是司机，并不是活跃用户，那如何判断他们还贷的概率需要数据。
</code></pre><ul>
<li>信用分的场景与典押有点类似，探讨可以协同的地方。</li>
</ul>
<h4 id="FAQ"><a href="#FAQ" class="headerlink" title="FAQ"></a>FAQ</h4><ul>
<li><p>不活跃的用户如何区分：80-20定律，大部分用户数据量很少；解决方法：提高数据丰度</p>
</li>
<li><p>如何区分是否虚假/恶意投诉：投诉率、进线率太高，人工进行审核</p>
</li>
</ul>
<h4 id="交叉验证"><a href="#交叉验证" class="headerlink" title="交叉验证"></a>交叉验证</h4><ul>
<li>平台有车乘客规模，乘客是否有房、是否有车的标签</li>
</ul>
<h4 id="介绍四方面的特征"><a href="#介绍四方面的特征" class="headerlink" title="介绍四方面的特征"></a>介绍四方面的特征</h4><ol>
<li><p>稳定性</p>
<p>异地高频生活、POI特征、统计类数据</p>
</li>
<li><p>反欺诈</p>
<p>是否高危职业客户</p>
</li>
<li><p>收入</p>
<p>车辆持有满3个月，固定收入预估区间，名下车产信息是否一致…</p>
</li>
<li><p>行为</p>
<p>近期生活轨迹重大变故、喜好预测…</p>
</li>
</ol>
<h4 id="介绍行为分"><a href="#介绍行为分" class="headerlink" title="介绍行为分"></a>介绍行为分</h4><p>初始化、权重计算、影响因子、增量更新</p>
<p>行为健康度介绍</p>
<p>用于免押的应用场景</p>
<h4 id="芝麻分"><a href="#芝麻分" class="headerlink" title="芝麻分"></a>芝麻分</h4><h2 id="待办"><a href="#待办" class="headerlink" title="待办"></a>待办</h2><p>排序之前的问题</p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://chenzk1.github.io/2019/11/19/7月23日/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Hero">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Hero's notebooks">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/11/19/7月23日/" itemprop="url">Untitled</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-19T10:23:10+08:00">
                2019-11-19
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>##吴文栋邮件</p>
<h3 id="先问能不能？再问如何？“滴滴如何树立自己在出行方面的权威形象？”滴滴虽然是一家平台，但只提供撮合交易的价值，是司机／乘客之外的第三方，但不一定能满足权威性要求。"><a href="#先问能不能？再问如何？“滴滴如何树立自己在出行方面的权威形象？”滴滴虽然是一家平台，但只提供撮合交易的价值，是司机／乘客之外的第三方，但不一定能满足权威性要求。" class="headerlink" title="先问能不能？再问如何？“滴滴如何树立自己在出行方面的权威形象？”滴滴虽然是一家平台，但只提供撮合交易的价值，是司机／乘客之外的第三方，但不一定能满足权威性要求。"></a>先问能不能？再问如何？“滴滴如何树立自己在出行方面的权威形象？”滴滴虽然是一家平台，但只提供撮合交易的价值，是司机／乘客之外的第三方，但不一定能满足权威性要求。</h3><ul>
<li>提供了平台，就得对平台进行管控，矛盾不可避免，而出现司乘之间无法自行调和的矛盾，则只能靠平台进行决断，因此这个权威性必须树立。要做的应该是尽量减少矛盾的出现，但矛盾一旦出现，要有足够的权威给予适当的调节手段。</li>
<li>减少矛盾：淘宝也是第三方平台，参考淘宝，是否可以有乘客自主选单的功能，设置距离优先、服务优先、车辆类型优先等，然后再按此派单，并在出现距离较远等情况时提醒用户是否确定发单，来减少取消订单的情况。</li>
<li>管控：司乘之间的协商，检测到绕路、高度收费时提醒司乘，并在客户端提示乘客做选择。</li>
<li>坏账能不能接入政府或其他的信用评分，以此增大乘客毁约的成本。</li>
</ul>
<h3 id="民不究官不治，与上同理，第三方平台，只有司乘出现自身无法调和的矛盾时才发挥作用。"><a href="#民不究官不治，与上同理，第三方平台，只有司乘出现自身无法调和的矛盾时才发挥作用。" class="headerlink" title="民不究官不治，与上同理，第三方平台，只有司乘出现自身无法调和的矛盾时才发挥作用。"></a>民不究官不治，与上同理，第三方平台，只有司乘出现自身无法调和的矛盾时才发挥作用。</h3><h2 id="网约车"><a href="#网约车" class="headerlink" title="网约车"></a>网约车</h2><h3 id="乘客信用分需要透传的底层数据必须要实锤，可用卷宗数据-也存在非实锤的问题-所有使用客服的数据的业务都存在这个问题，相信这个问题终会解决-卷宗？"><a href="#乘客信用分需要透传的底层数据必须要实锤，可用卷宗数据-也存在非实锤的问题-所有使用客服的数据的业务都存在这个问题，相信这个问题终会解决-卷宗？" class="headerlink" title="乘客信用分需要透传的底层数据必须要实锤，可用卷宗数据(也存在非实锤的问题, 所有使用客服的数据的业务都存在这个问题，相信这个问题终会解决);卷宗？"></a>乘客信用分需要透传的底层数据必须要实锤，可用卷宗数据(也存在非实锤的问题, 所有使用客服的数据的业务都存在这个问题，相信这个问题终会解决);卷宗？</h3><ul>
<li>乘客信用很重要，是我们的抓手之一，但是好像跟我们的业务关系不太大，希望定制化分数; 信用是历史的表现行为的累计，用历史的行为来判责判罚当次发生的问题，持谨慎态度”</li>
<li>那如何解决呢？对判责仅提供参考，主要还是用来例如降低押金或免押金，或恶意乘客识别（说明历史上有多次恶意或不好的行为）</li>
<li>理想中是有很多作用，具体实施要考虑到业务（足够的依据）、用户的…等</li>
<li>目前定位是分层管控，但是管控却没有足够的依据。判责的标准不好改变，是否可以考虑多次不好的行为后实施惩罚或者账号的某些动作限制？例如信用分太低限制在发单几分钟之后取消订单？ </li>
</ul>
<h3 id="一期信用分的目的是对乘客去尾，尾部乘客可以分成两部分，其中一部分是高频小问题的乘客。"><a href="#一期信用分的目的是对乘客去尾，尾部乘客可以分成两部分，其中一部分是高频小问题的乘客。" class="headerlink" title="一期信用分的目的是对乘客去尾，尾部乘客可以分成两部分，其中一部分是高频小问题的乘客。"></a>一期信用分的目的是对乘客去尾，尾部乘客可以分成两部分，其中一部分是高频小问题的乘客。</h3><ul>
<li>因为客服不会对服务类投诉判责(比如抽烟、醉酒、超载等)所以无实锤证据，由于我们的实锤机制，我们无法对这类行为做扣分处理，这就会导致高频小问题的乘客不会被我们管控。不做管控，但间接提醒，例如既然同类问题高频出现，那认为此人确实有此类问题的置信度比较高，因此可以考虑发送短信提醒（如果在提醒中加上，如若再犯会影响平台对你之后行为的判责以及打车发单的优先级，这样之后再应用行为分做管控的时候合理吗？或者不做判责）</li>
</ul>
<h3 id="方案细节"><a href="#方案细节" class="headerlink" title="方案细节"></a>方案细节</h3><h4 id="特征"><a href="#特征" class="headerlink" title="特征"></a>特征</h4><ul>
<li>分5个等级评价，但是大部分人是默认好评，直接混入好评差评率作为特征会引入噪声吧，是否可以考虑标记默认好评数，再排除默认好评求取差评率好评率。</li>
<li>很多行为，例如抽烟、吃东西、喝酒等，并不是每位司机都会在平台上报备，这样的话直接拿这些行为用作特征，这个合理吗？因为这虽然是现实数据，但其实并不是实际中的真实分布（有人抽烟，但平台记录为无），所以此类行为加入到模型中怎样应用呢？</li>
<li>以投诉或差评为label，如果是恶意投诉或恶意差评呢？怎样去躁？或者提示模型的鲁棒性？这个用起来应该更长久一点。</li>
<li>性骚扰、盗窃、抢劫，这些极端恶劣性行为不一定有石锤，考虑直接客服介入？</li>
</ul>
<h4 id="Label"><a href="#Label" class="headerlink" title="Label"></a>Label</h4><ul>
<li>一次坏行为，一月坏行为率，行为*权重。这是用于评分卡模型的。有没有其他模型呢？更多的模型就能考虑更多要素。</li>
<li>所有新用户有一个基本分，后续增量变化，以此生成信用分，但是这个现实吗？早期数据够不够？</li>
</ul>
<h4 id="模型"><a href="#模型" class="headerlink" title="模型"></a>模型</h4><ul>
<li>信用分增量更新的具体考量。高分速率放缓、加减分权重…</li>
<li>相当于异常检测，所以直接做统计检验来产生概率是否可以作为一个模型</li>
</ul>
<h2 id="信用分调研2019"><a href="#信用分调研2019" class="headerlink" title="信用分调研2019"></a>信用分调研2019</h2><h3 id="项目推进节奏"><a href="#项目推进节奏" class="headerlink" title="项目推进节奏"></a>项目推进节奏</h3><ul>
<li><p>乘客行为分 推动 乘客露出 比较难，水下则会容易得多。出现这种情况的原因主要在于，乘客行为分本质需要乘客完成隐私授权，作为对等交换，应当通过提供权益的方式达成这一目的。之前推动乘客侧的露出，主要是希望达成管控目标，这和乘客的期待有本质的冲突。</p>
<p>就是说向乘客露出了行为分那就得给乘客提供相应权益（乘客付出了隐私；乘客对信用分没有需求，所以用其他手段刺激需求），免押？打折/优惠券？满级奖励？接入芝麻分/信用评级？</p>
</li>
</ul>
<h3 id="评估指标"><a href="#评估指标" class="headerlink" title="评估指标"></a>评估指标</h3><h2 id="FAQ"><a href="#FAQ" class="headerlink" title="FAQ"></a>FAQ</h2><ul>
<li><p><strong>评分卡模型</strong></p>
<p><em>F: 未来一段时间内是否出现恶劣行为 是很好的建模目标么？如何评估一个建模目标的好坏？</em></p>
<p>A: </p>
<ul>
<li>评分卡模型本质是一个二分类，因此离线指标为分类模型可用的指标：AUC/Recall/Precision/F1/Accuracy…</li>
<li>模型生成的分数在线上评估时有两个维度，区分度评估：K-S, GINI（还有其他的吗？树模型里面选择特征以及分裂点的指标例如信息增益、信息增益比等本质也是衡量区分度的，应该改改可以用吧）；稳定度评估：中位数</li>
<li>业务当中，为评价此指标的引入创造的价值还应该有业务指标的评价：坏账率、注册完单率、CPO、司机&amp;乘客NPS、GMV…（多个维度）<strong>业务上的评价应该是根本性的评价</strong></li>
</ul>
</li>
<li><p>信用分是历史行为的积累，但是用历史的行为来判责当次发生的问题显得依据不够，因此在内部推行的时候也遇到了不少困难，是否可以考虑对判责仅提供参考，但可以应用于例如降低押金、免押金、或恶意乘客识别（说明历史上有多次恶意行为）</p>
<p><em>F: “仅提供参考”是高价值／高优先级 的目标么？如果不是，哪些是高价值／高优先级 的目标。</em></p>
<p>A: 既然是只提供参考，那就不是高价值 / 高优先级的目标，高价值 / 高优先级的目标：履约能力（免押金、免预付，减少坏账）；减少取消率；提高司机NPS。BTW: 既然是在判责的时候用历史行为显得依据不够，那能不能把信用分应用于一个单子生命后期的更早期呢，例如预防坏账、预防取消、增强司机的体验…。</p>
</li>
<li><p>目前信用分对内部的定位是分层管控，但是管控却没有足够的依据，那是否可以考虑多次恶意行为后实施惩罚或者账号的某些动作限制，例如信用分太低则适当限制在发单之后取消订单等操作。 </p>
<p><em>F: 信用分的定位</em></p>
<p>A: </p>
</li>
</ul>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
  </section>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/5/">5</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right"></i></a>
  </nav>



          </div>
          


          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview sidebar-panel sidebar-panel-active">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image" src="/images/avatar.jpg" alt="Hero">
          <p class="site-author-name" itemprop="name">Hero</p>
           
              <p class="site-description motion-element" itemprop="description">hero's notebooks</p>
          
        </div>
        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
              <a href="/archives/">
                <span class="site-state-item-count">47</span>
                <span class="site-state-item-name">posts</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">1</span>
                <span class="site-state-item-name">categories</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">26</span>
                <span class="site-state-item-name">tags</span>
              </a>
            </div>
          

        </nav>

        
          <div class="feed-link motion-element">
            <a href="/atom.xml" rel="alternate">
              <i class="fa fa-rss"></i>
              RSS
            </a>
          </div>
        

        <div class="links-of-author motion-element">
          
        </div>

        
        

        
        

        


      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Hero</span>
</div>


<div class="powered-by">
  Powered by <a class="theme-link" href="https://hexo.io">Hexo</a>
</div>

<div class="theme-info">
  Theme -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>


        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.2"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.2"></script>



  
    <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.2"></script>

  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.2"></script>



  


  




	





  





  






  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  

  

  

  

</body>
</html>
